import jwt
from datetime import datetime, timedelta, timezone
from typing import Any
from config import app_settings


class JwtUtil:
    """
        jwt包含三部分（jwt.encode）：base64(header).base64(payload).base64(签名)
            ①前两部分直接base64_decode就可以解密成明文
            ②签名计算方法：base64(header).base64(payload)组成字符串P  -->  加密(P,秘钥)得到加密串C即为签名

        验证接口传递jwt签名验证过程：
            base64_decode(jwt第三部分) == 加密(jwt前两部分,秘钥)  即可验证接口传递签名

        jwt.decode包含的验证过程：
            ①默认会验证jwt的签名，验证失败会抛出异常InvalidSignatureError。验证逻辑：api_jws.py#decode_complete。
              如果在decode时不需要验证签名，可以通过options传递verify_signature=False
            ②除了验证签名外，还支持验证payload部分的exp、nbf、iat、aud和iss五个字段。默认不验证，可以通过options的
              verify_exp、verify_nbf、verify_iat、verify_aud和verify_iss进行开启对应的验证功能。对应逻辑：api_jwt.py#decode_complete
    """

    @classmethod
    def create_access_token(cls, payload: dict[str, Any], expires_delta: timedelta | None = None) -> str:
        to_encode = payload.copy()
        nowtime = datetime.now(timezone.utc)
        if expires_delta:
            expire = nowtime + expires_delta
        else:
            expire = nowtime + timedelta(minutes=app_settings.ACCESS_TOKEN_EXPIRE_MINUTES)
        to_encode.update({"exp": expire})
        to_encode.update({"iat": nowtime})
        encoded_jwt = jwt.encode(to_encode, app_settings.SECRET_KEY, algorithm=app_settings.ALGORITHM)
        return encoded_jwt

    @classmethod
    def decode_access_token_payload_and_verify_exp(cls, jwt_token: str) -> dict:
        return jwt.decode(jwt_token, app_settings.SECRET_KEY, algorithms=[app_settings.ALGORITHM],
                          options=dict(verify_signature=True, verify_exp=False))
